using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net.Security;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;

namespace LFromeWork
{
    /// <summary>
    /// 版本文件 管理器
    /// </summary>
    public class VersionFileManager
    {
        #region cdn 资源 真正的资源地址
        private string m_RealCDNSourceUrl;
        /// <summary>
        /// 真正的资源地址
        /// </summary>
        public string RealCDNSourceUrl
        {
            get
            {
                if (string.IsNullOrEmpty(m_RealCDNSourceUrl))
                {
                    string buildTarget = string.Empty;

#if UNITY_STANDALONE_WIN
                buildTarget = "Windows";
#elif UNITY_ANDROID
				buildTarget = "Android";
#elif UNITY_IPHONE
                    buildTarget = "iOS";
#endif
                    m_RealCDNSourceUrl = string.Format("{0}{1}/{2}/", GameLaunch.ParamsSettings.CDNUrl, CDNVersionNumber, buildTarget);
                }
                return m_RealCDNSourceUrl;
            }
        }
        #endregion
        
        #region CDN
        /// <summary>
        /// CDN资源版本号
        /// </summary>
        private string m_CDNVersionNumber;

        /// <summary>
        /// CDN资源版本号
        /// </summary>
        public string CDNVersionNumber { get { return m_CDNVersionNumber; } }

        /// <summary>
        /// CDN资源包信息
        /// </summary>
        public Dictionary<string, VersionFileEntity> m_CDNVersionDic = new Dictionary<string, VersionFileEntity>();

        /// <summary>
        /// 获取 服务器 游戏版本号
        /// </summary>
        public void GetServerVersionNumber(int gameId,string clientVersion, Action<bool> callBack = null)
        {
            string url = string.Format("{0}version?gameId={1}&clientVersion={2}",GameLaunch.Http.RealWebAccountUrl, gameId, clientVersion);
            GameLaunch.Http.Get(url, (args) => {
                bool isError = args.HasError;
                if (!args.HasError) 
                {
                    isError = args.Value.JsonCutApart("Status").ToInt() != (int)HttpResultStatus.Success;
                    if (!isError) 
                    {
                        m_CDNVersionNumber = args.Value.JsonCutApart("Content").JsonCutApart("Version");
                    }
                }
                callBack?.Invoke(isError);
            });
        }

        /// <summary>
        /// 初始化CDN的版本文件信息
        /// </summary>
        public void InitCDNVersionFile(Action onInitComplete)
        {
            StringBuilder sbr = new StringBuilder();
            string url = sbr.AppendFormat("{0}{1}", RealCDNSourceUrl, LFConstDefine.VersionFileName).ToString();

            IEnumerator UnityWebRequestGet(string url, Action<UnityWebRequest> onComplete)
            {
                using (UnityWebRequest request = UnityWebRequest.Get(url))
                {
                    yield return request.SendWebRequest();
                    onComplete?.Invoke(request);
                }
            }
            GameLaunch.Instance.StartCoroutine(UnityWebRequestGet(url, (request) =>
            {
                if (request.result == UnityWebRequest.Result.Success)
                {
                    m_CDNVersionDic = GetAssetBundleVersionList(request.downloadHandler.data);
                    Debug.Log("OnInitCDNVersionFile");
                    onInitComplete?.Invoke();
                }
                else
                {
                    Debug.Log("初始化CDN资源包信息失败，url==" + url);
                }
            }));
        }

        /// <summary>
        /// 获取CDN上的资源包的版本信息(这个方法一定要能返回信息)
        /// </summary>
        /// <param name="assetbundlePath"></param>
        /// <returns></returns>
        public VersionFileEntity GetVersionFileEntity(string assetbundlePath)
        {
            VersionFileEntity entity = null;
            m_CDNVersionDic.TryGetValue(assetbundlePath, out entity);
            return entity;
        }

        #endregion

        #region 可写区

        private string m_LocalVersionFilePath = null;
        /// <summary>
        /// 可写区 版本文件路径
        /// </summary>
        public string LocalVersionFilePath
        {
            get
            {
                if (m_LocalVersionFilePath == null)
                {
                    m_LocalVersionFilePath = string.Format("{0}/{1}", Application.persistentDataPath, LFConstDefine.VersionFileName);
                }
                return m_LocalVersionFilePath;
            }
        }

        /// <summary>
        /// 可写区资源版本号
        /// </summary>
        public string LocalVersionNumber { get { return m_LocalVersionNumber; } }
        private string m_LocalVersionNumber;

        /// <summary>
        /// 可写区资源包信息
        /// </summary>
        public Dictionary<string, VersionFileEntity> m_LocalAssetsVersionDic = new Dictionary<string, VersionFileEntity>();

        /// <summary>
        /// 获取本地 游戏版本号
        /// </summary>
        public void GetLocalVersionNumber(int gameId)
        {
            string localVersionNumberPath = string.Format("{0}/{1}", Application.persistentDataPath, LFConstDefine.VersionNumberName);
            //说明第一次安装，初始化 streaming 文件 到 沙盒路径下
            if (!File.Exists(localVersionNumberPath))
            {
                //VersionFile
                File.Copy(StreamingVersionFilePath, LocalVersionFilePath);

                //AssetInfo
                string streamingAssetInfoPath = string.Format("{0}/{1}/{2}", Application.streamingAssetsPath, LFConstDefine.AssetBundles, LFConstDefine.AssetInfoName);
                string localAssetInfoPath = string.Format("{0}/{1}", Application.persistentDataPath, LFConstDefine.AssetInfoName);
                File.Copy(streamingAssetInfoPath, localAssetInfoPath);

                //VersionNumber
                string streamingVersionNumberPath = string.Format("{0}/{1}/{2}", Application.streamingAssetsPath, LFConstDefine.AssetBundles, LFConstDefine.VersionNumberName);
                File.Copy(streamingVersionNumberPath, localVersionNumberPath);
            }

            m_LocalVersionNumber = File.ReadAllText(localVersionNumberPath);
        }

        /// <summary>
        /// 初始化本地版本文件
        /// </summary>
        public void InitLocalVersionFile()
        {
            byte[] versionByte = IOUtil.GetFileBuffer(LocalVersionFilePath);
            m_LocalAssetsVersionDic = GetAssetBundleVersionList(versionByte);
        }

        /// <summary>
        /// 保存可写区版本信息
        /// </summary>
        /// <param name="entity"></param>
        public void SaveVersion(VersionFileEntity entity)
        {
            m_LocalAssetsVersionDic[entity.AssetBundleName] = entity;

            //保存版本文件
            string json = m_LocalAssetsVersionDic.ToJson();
            IOUtil.CreateTextFile(LocalVersionFilePath, json);
        }

        /// <summary>
        /// 保存可写区资源版本号
        /// </summary>
        public void SetVersionNumber(string version)
        {
            m_LocalVersionNumber = version;
            File.WriteAllText(LocalVersionFilePath, m_LocalVersionNumber);
        }

        /// <summary>
        /// 获取可写区版本文件是否存在
        /// </summary>
        /// <returns></returns>
        public bool GetVersionFileExists()
        {
            return File.Exists(LocalVersionFilePath);
        }
        #endregion
        
        #region StreamingAsset 区

        private string m_StreamingVersionFilePath = null;
        /// <summary>
        /// StreamingAsset 区 版本文件路径
        /// </summary>
        public string StreamingVersionFilePath
        {
            get
            {
                if (m_StreamingVersionFilePath == null)
                {
                    m_StreamingVersionFilePath = string.Format("{0}/{1}/{2}", Application.streamingAssetsPath,LFConstDefine.AssetBundles, LFConstDefine.VersionFileName);
                }

                return m_StreamingVersionFilePath;
            }
        }
        #endregion
        
        /// <summary>
        /// 根据字节数组获取资源包版本信息
        /// </summary>
        /// <param name="buffer">字节数组</param>
        /// <param name="version">版本号</param>
        /// <returns></returns>
        public Dictionary<string, VersionFileEntity> GetAssetBundleVersionList(byte[] buffer)
        {
            buffer = ZlibHelper.DeCompressBytes(buffer);

            Dictionary<string, VersionFileEntity> dic = new Dictionary<string, VersionFileEntity>();

            MMO_MemoryStream ms = new MMO_MemoryStream(buffer);

            int len = ms.ReadInt();

            for (int i = 0; i < len; i++)
            {
                VersionFileEntity entity = new VersionFileEntity();
                entity.AssetBundleName = ms.ReadUTF8String();
                entity.MD5 = ms.ReadUTF8String();
                entity.Size = ms.ReadULong();
                entity.IsFirstData = ms.ReadByte() == 1;

                dic[entity.AssetBundleName] = entity;
            }
            return dic;
        }

        public void Dispose()
        {
            m_CDNVersionDic.Clear();
            m_CDNVersionDic = null;
            m_LocalAssetsVersionDic.Clear();
            m_LocalAssetsVersionDic = null;
        }
    }
}